package edu.xhu.im.processor;

import cn.hutool.core.bean.BeanUtil;
import edu.xhu.im.server.IMServerGroup;
import edu.xhu.im.server.UserChannelCtxMap;
import edu.xhu.model.im.constant.ChannelAttrKey;
import edu.xhu.model.im.constant.IMConstant;
import edu.xhu.model.im.constant.IMRedisKey;
import edu.xhu.model.im.enums.IMCmdType;
import edu.xhu.model.im.pojos.IMLoginInfo;
import edu.xhu.model.im.pojos.IMSendInfo;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.AttributeKey;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
@RequiredArgsConstructor
public class LoginProcessor extends AbstractMessageProcessor<IMLoginInfo> {

    private final StringRedisTemplate redisTemplate;

    @Override
    public synchronized void process(ChannelHandlerContext ctx, IMLoginInfo loginInfo) {
        Long userId = null;
//        if (loginInfo.getAccessToken() == null || loginInfo.getAccessToken().isEmpty()) {
//            ctx.channel().close();
//            log.warn("用户token校验不通过，强制下线,token:{}", loginInfo.getAccessToken());
//        }
//        // 解析token
//        Claims claims = AppJwtUtil.getClaimsBody(loginInfo.getAccessToken());
//        if (claims == null) {
//            ctx.channel().close();
//            log.warn("用户token校验不通过，强制下线,token:{}", loginInfo.getAccessToken());
//        } else {
//            //解析出userId
//            userId = (Long) claims.get("id");
//        }
        String user = new String("abc");
        userId = loginInfo.getUserId();     //TODO:测试
        if (userId == null) {
            ctx.channel().close();
            log.warn("用户token校验不通过，强制下线,token:{}", loginInfo.getAccessToken());
        } else {
            //前置工作完毕
            Integer terminal = 0;   //目前写死,默认是0,web
            log.info("用户登录，userId:{}", userId);
            ChannelHandlerContext context = UserChannelCtxMap.getChannelCtx(userId, terminal);
            if (context != null && !ctx.channel().id().equals(context.channel().id())) {
                // 不允许多地登录,强制下线
                IMSendInfo<Object> sendInfo = new IMSendInfo<>();
                sendInfo.setCmd(IMCmdType.FORCE_LOGUT.code());
                sendInfo.setData("您已在其他地方登陆，将被强制下线");
                context.channel().writeAndFlush(sendInfo);
                log.info("异地登录，强制下线,userId:{}", userId);
            }
            // 绑定用户和channel
            UserChannelCtxMap.addChannelCtx(userId, terminal, ctx);
            // 设置用户id属性
            AttributeKey<Long> userIdAttr = AttributeKey.valueOf(ChannelAttrKey.USER_ID);
            ctx.channel().attr(userIdAttr).set(userId);
            // 设置用户终端类型
            AttributeKey<Integer> terminalAttr = AttributeKey.valueOf(ChannelAttrKey.TERMINAL_TYPE);
            ctx.channel().attr(terminalAttr).set(terminal);
            // 初始化心跳次数
            AttributeKey<Long> heartBeatAttr = AttributeKey.valueOf("HEARTBEAt_TIMES");
            ctx.channel().attr(heartBeatAttr).set(0L);
            // 在redis上记录每个user的channelId，15秒没有心跳，则自动过期
            String key = String.join(":", IMRedisKey.IM_USER_SERVER_ID, userId.toString(), terminal.toString());
            redisTemplate.opsForValue().set(key, String.valueOf(IMServerGroup.serverId), IMConstant.ONLINE_TIMEOUT_SECOND, TimeUnit.SECONDS);
            // 响应ws
            IMSendInfo<Object> sendInfo = new IMSendInfo<>();
            sendInfo.setCmd(IMCmdType.LOGIN.code());
            ctx.channel().writeAndFlush(sendInfo);
            //当前用户在线状态
            log.info("当前用户的在线状态:{}", UserChannelCtxMap.getChannelCtx(userId));
        }
    }


    @Override
    public IMLoginInfo transForm(Object o) {
        HashMap map = (HashMap) o;
        return BeanUtil.fillBeanWithMap(map, new IMLoginInfo(), false);
    }

    /**
     * 通过token,解析user出来
     */
    private String validateToken(String token) {
        return null;
    }

}
